#include "riscv_math.h"
#include <stdint.h>
#include <stdlib.h>
#include "../common.h"

#include "../HelperFunctions/math_helper.c"
#include "../HelperFunctions/ref_helper.c"

#include <stdio.h>
#define DELTAF32 (0.05f)
#define DELTAQ31 (63)
#define DELTAQ15 (1)
#define DELTAQ7 (1)

int test_flag_error = 0;

/* 
  The sigmoid SVM instance containing all parameters.
  Those parameters can be generated with the python library scikit-learn.
 */
riscv_svm_sigmoid_instance_f32 params;

/*
  Parameters generated by a training of the SVM classifier
  using scikit-learn and some random input data.
 */
#define NB_SUPPORT_VECTORS 2

/*
  Dimension of the vector space. A vector is your feature.
  It could, for instance, be the pixels of a picture or the FFT of a signal.
 */
#define VECTOR_DIMENSION 2

const float32_t dualCoefficients[NB_SUPPORT_VECTORS]={-0.5006101f,0.5006101f}; /* Dual coefficients */

const float32_t supportVectors[NB_SUPPORT_VECTORS*VECTOR_DIMENSION]={-1.33358633f,3.46798561f,-0.56781298f,-2.79117593f}; /* Support vectors */

/*
  Class A is identified with value 0.
  Class B is identified with value 1.
  
  This array is used by the SVM functions to do a conversion and ease the comparison
  with the Python code where different values could be used.
 */
const int32_t   classes[2]={0,1};

int main()
{
    int i;
    BENCH_INIT;
    /* Array of input data */
    float32_t in[VECTOR_DIMENSION];

    /* Result of the classifier */
    int32_t result;
    

    /*
        Initialization of the SVM instance parameters.
        Additional parameters (intercept, degree, coef0 and gamma) are also coming from Python.
    */
    riscv_svm_sigmoid_init_f32(&params,
        NB_SUPPORT_VECTORS,
        VECTOR_DIMENSION,
        0.000017f,        /* Intercept */
        dualCoefficients,
        supportVectors,
        classes,
        1.100000f,         /* Coef0 */
        0.500000f          /* Gamma */
    );


    /*
        Input data.
        It is corresponding to a point inside the first class.
    */
    in[0] = 0.4f;
    in[1] = 0.1f;
    BENCH_START(riscv_svm_sigmoid_predict_f32);
    riscv_svm_sigmoid_predict_f32(&params, in, &result);
    BENCH_END(riscv_svm_sigmoid_predict_f32);
    /* Result should be 0 : First class */
    if (result != 0) {
        BENCH_ERROR(riscv_svm_sigmoid_predict_f32);
        printf("expect: %d, actual: %d\n", 0, result);
        test_flag_error = 1;
    }
    BENCH_STATUS(riscv_svm_sigmoid_predict_f32);

    /*
        This input vector is corresponding to a point inside the second class.
    */
    in[0] = 3.0f;
    in[1] = 0.0f;

    riscv_svm_sigmoid_predict_f32(&params, in, &result);

    /* Result should be 0 : First class */
    if (result != 1) {
        BENCH_ERROR(riscv_svm_sigmoid_predict_f32);
        printf("expect: %d, actual: %d\n", 1, result);
        test_flag_error = 1;
    }
    BENCH_STATUS(riscv_svm_sigmoid_predict_f32);


    BENCH_FINISH;
    if (test_flag_error) {
        printf("test error apprears, please recheck.\n");
        return 1;
    } else {
        printf("all test are passed. Well done!\n");
    }
    return 0;
};
